perm filename TEST[P,JRA] blob
sn#544195 filedate 1980-10-28 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00004 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 (DE EVAL (X ENV)
C00007 00003 3. In the presence of side-effects, it is useful to extend the syntax
C00010 00004 8. Assuming a representation of sets as sequences, write algorithms for set union,
C00014 ENDMK
C⊗;
(DE EVAL (X ENV)
(COND ((IS-CONST X) (VAL X))
((IS-VAR X) (LOOKUP X ENV))
((IS-IF X) (IF (EVAL (PREM X) ENV)
(EVAL (CONSE X) ENV)
(EVAL (ANTE X) ENV)))
((IS-LAM X) (MK-FUNARG (FORM X)
(BODY X)
(ENV)))
(T (APPLY (EVAL (FUN X) ENV)
(EVLIS (ARGS X) ENV)
ENV))))
(DE APPLY (FN EARGS ENV)
(COND ((IS-PRIM FN) (DOIT FN EARGS))
((IS-FUNARG FN) (EVAL (BODY FN)
(MK-ENV (FORM FN)
EARGS
ENV)))
(DE EVLIS (L ENV)
(IF (NULL L)
( )
(CONCAT (EVAL (FIRST L) ENV)
(EVLIS (REST L) ENV))))
(DE LOOKUP (N ST)
(COND ((NULL ST) error)
((IN N (BLOCK ST)) (VALUE N (BLOCK ST)))
(T (LOOKUP N (TAIL ST)))))
1. Consider the code for LOOKUP; it is basically rotten: we use IN to search the
name-compoment of a block and, if a match is found, we use VALUE (rather magically,
in fact) to extract the value associated with that name. This requires that we run
through a block TWICE if a name is located (in fact, VALUE duplicates much of IN).
Rewrite LOOKUP (without assigment statements!) so that we traverse a block only once.
2. The reason for writing LOOKUP initially in this dreadful fashion was to illustrate
a common computing phenomenon: namely, if a computation gives "false" then we go away
and do something else; however, if the computation gives a non-false value them we
want to do further processing on that value. For example in LOOKUP, we might expect a
new version of IN, called IN1, to return either "false" --i.e. NIL-- or an encoding
of the value associated with the name; in the latter case, we need only extract that
value (--careful! we must be able to recognize the difference between NIL meaning
"no value found" and NIL as the current value for the name). Less elegant languages
resort to some kind of assignment statement to save the intermediate result. indeed,
such a hack can also be done in LISP:
(DE LOOKUP (N ST)
(COND ((NULL ST) error)
((SETQ XX (IN1 N (BLOCK ST))) (EXTRACT XX))
(T (LOOKUP N (TAIL ST)))))
...indeed ugly, because XX is not bound within the definition of lookup. A solution
to this difficult is outlined on page 255 of Anatomy:
test[<p>;<f>; <b>] is defined such that if <p> returns a NIL value then <b> is
evaluated, otherwise the unary function, <f> is applied to the value of <p>. For
example, (DE LOOKUP (N ST)
(IF (NULL ST)
error
(TEST (IN1 N (BLOCK ST)) EXTRACT (LOOKUP N (TAIL ST)))))
The problem: extend the EVAL-APPLY pair to recognize and evaluate TEST expressions.
3. In the presence of side-effects, it is useful to extend the syntax
(and semantics) of the language as follows:
a: a function body may contain several expressions:
(DE FOO (X Y) e1 e2 ... en)
b: a conditional expression may have several actions for each predicate expression:
(COND (p1 e11 e11 e12 ... e1n)
(p2 e21 e22 .... e2m)
... )
in each of these cases we wish the expression sequence to be evaluated sequentially
from left-to-right. Indicate what changes must be made to the evaluator to reflect
these extensions.
4. One (at least one!) language feature that we have not implemented in our evaluator
is DE, i.e. the semantics of function definition. Assuming that we have SETQ
defined, extend the evaluator to support DE
5. Given the following functions:
(DE PAIR (X Y)
(LAMBDA (SEL) (IF (EQ SEL 0)
X
Y)))
(DE HEAD (X) (X 0)) and (DE TAIL (X) (X 1))
evaluate: (HEAD (PAIR 'A 'B)) and (TAIL (PAIR 1 2))
6. We wish to represent tree-structures whose nodes are either terminal, or consist
of three items: a left branch, a right branch, and an "information" component, N:
N
/ \
/ \
L R
write abstract algorithms that encode the following orders of visitation: (a) L-R-N
(b) L-N-R, and (c) N-L-R. You may use the results of problem 3. How much does the
semantics of the language influence your solution.
Suggest a sequence implementation of these trees and supply appropriate selectors,
recognizers, and constructors.
7. Consider the following definition:
(DE APPEND (X Y)
(IF (NULL X)
Y
(CONCAT (FIRST X)
(APPEND (REST X) Y))))
prove that (APPEND X (APPEND Y Z)) ≡ (APPEND (APPEND X Y) Z)
8. Assuming a representation of sets as sequences, write algorithms for set union,
intersection, and power set (the set of all subsets of a set). Write a predicate to
test for set membership.
9. Consider, the Towers of Hanoi puzzle: given three vertical rods and a stack of
discs on one rod, arranged by size such that the largest is on the bottom; move the
discs to the adjacent rod, subject to the constraints that only one disc may be moved
at a time, and no disc may be placed on top of a smaller disc.
Write a recursive algorithm to describe the solution, and give a justification that
your solution is correct.
10. Consider a language for propositional logic:
(1) a potentially infinite collection of names: p, r, q, ...x, y, z, p1, ...;
(2) two constants, T, and F;
and (3) logical functions ∧, ∨, ¬, ≡,
subject to the following definitions:
(A) expressions of the language are defined as follows:
1. a name or constant is an expression
2. if α and β are expressions then ¬(α) (α)∨(β), (α)∧(β), and (α)≡(β)
are expressions
3. expressions are only made by application of rules 1. and 2.
(B) the functions are defined as follows:
α | ¬α α β | α∨β α β | α∧β α β | α≡β
------ ---------- ------------ -----------
T | F T T | T T T | T T T | T
F | T T F | T T F | F T F | F
F T | T F T | F F T | F
F F | F F F | F F F | T
Give a sequence-representation for expressions of this language. Write an algorithm,
TAUTOLOGY, of one argument <exp>, where <exp> represents an expression in the
language and TAUTOLOGY is to give T as value just in the case that <exp> has value T
for all possible assignments of values to names appearing in <exp>.
For example:
expression value for TAUTOGOLY
T T
p∨T T
p∧T F (give p the value F)
(p∧q)≡(q∧p) T
(¬¬p)≡p T